package shop.order.service.impl;


import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.IdWorker;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import lombok.RequiredArgsConstructor;
import org.springframework.stereotype.Service;
import org.springframework.util.ObjectUtils;
import shop.common.core.Result;
import shop.common.entity.Order;
import shop.common.entity.OrderItem;
import shop.common.entity.Product;
import shop.common.entity.User;
import shop.common.utils.ConvertUtil;
import shop.order.mapper.OrderItemMapper;
import shop.order.mapper.OrderMapper;
import shop.order.remote.RemoteCartService;
import shop.order.remote.RemoteProductService;
import shop.order.remote.RemoteUserService;
import shop.order.service.OrderService;

import java.math.BigDecimal;
import java.util.List;
import java.util.stream.Collectors;

@Service
@RequiredArgsConstructor
public class OrderServiceImpl extends ServiceImpl<OrderMapper, Order> implements OrderService {

    private final OrderItemMapper orderItemMapper;
    private final RemoteProductService productService;
    private final RemoteCartService cartService;
    private final RemoteUserService userService;

    @Override
    public Page<Order> list(Order order, Integer pageNum, Integer pageSize) {
        LambdaQueryWrapper<Order> wrapper = Wrappers.lambdaQuery(Order.class)
                .eq(!ObjectUtils.isEmpty(order.getId()), Order::getId, order.getId())
                .eq(!ObjectUtils.isEmpty(order.getStatus()), Order::getStatus, order.getStatus());

        Page<Order> page = new Page<>(pageNum, pageSize);
        this.page(page, wrapper);
        List<Order> list = page.getRecords().stream()
                .map(item -> this.details(item.getId()))
                .collect(Collectors.toList());
        page.setRecords(list);
        return page;
    }

    @Override
    public Order details(String id) {
        Order order = baseMapper.selectById(id);
        Result userResult = userService.details(order.getUserId());
        User user = ConvertUtil.cast(userResult.getData(), User.class);
        order.setUser(user);


        List<OrderItem> orderItemList = orderItemMapper.selectList(Wrappers.lambdaQuery(OrderItem.class).eq(OrderItem::getOrderId, order.getId()));
        for (OrderItem orderItem : orderItemList) {
            Result result = productService.details(orderItem.getProductId());
            Product product = ConvertUtil.cast(result.getData(), Product.class);
            orderItem.setProduct(product);
        }

        order.setOrderItemList(orderItemList);
        return order;

    }

    @Override
    public List<Order> listByUserId(String userId) {
        List<Order> orderList = baseMapper.selectList(Wrappers.<Order>lambdaQuery().eq(Order::getUserId, userId));

        return orderList.stream().map(order -> details(order.getId())).collect(Collectors.toList());
    }

    @Override
    public boolean createOrder(String userId, String address, List<OrderItem> orderItemList) {

        String orderId = String.valueOf(IdWorker.getId());
        Integer totalQuantity = orderItemList.size();
        BigDecimal totalPrice = BigDecimal.ZERO;

        for (OrderItem orderItem : orderItemList) {
            Result result = productService.details(orderItem.getProductId());
            Product product = ConvertUtil.cast(result.getData(), Product.class);
            totalPrice = totalPrice.add(product.getPrice().multiply(new BigDecimal(orderItem.getQuantity())));
            orderItem.setOrderId(orderId);
            orderItemMapper.insert(orderItem);


            cartService.removeByUserIdAndProductId(userId, product.getId());
        }

        Order order = new Order();
        order.setId(orderId);
        order.setAddress(address);
        order.setTotalPrice(totalPrice);
        order.setTotalQuantity(totalQuantity);
        order.setUserId(userId);
        int insert = baseMapper.insert(order);
        return insert > 0;
    }
}




